//= require <framework/w3c/events/EventTarget>
//= require <framework/w3c/models/NodeType>
//= require <framework/w3c/traits/CSSSelectors>

namespace("w3c.Node", {
    '@traits': [w3c.EventTarget, w3c.CSSSelectors],
	
	nodeType : w3c.NodeType.ELEMENT_NODE,
    nodeName : "div",
	nodeValue: "",
    
    preInitialize : function(model, element){
        this.element = element;
        this.model 	 = model;
    },
    
    parentNode: function(element){
    	element = element||this.element;
		return element.parentNode;
    },
    
    childNodes: function(element){
    	element = element||this.element;
		return element.childNodes;
    },
    
    firstChild: function(element){
		element = element||this.element;
        var fc = element.firstChild;
        while (fc.nodeType != 1) {
            fc = fc.nextSibling;
        };
        return fc;
    },
    
    lastChild: function(element){
		element = element||this.element;
        var lc = element.lastChild;
        while (lc.nodeType != 1) {
            lc = lc.previousSibling;
        }
        return lc;
    },
    
    previousSibling: function(element){
		element = element || this.element;
        do {element = element.previousSibling;} while (element && element.nodeType != 1);
        return element;
    },
    
    nextSibling: function(element){
		element = element || this.element;
        do {element = element.nextSibling;} while (element && element.nodeType != 1);
        return element;
    },
    
    attributes: function(){
		element = element || this.element;
		return element.attributes;
    }, //NamedNodeMap
    
    ownerDocument: function(element){
    	element = element || this.element;
		return element.ownerDocument;
    },
    
	insertAfter : function(newElement, referenceElement, element) {
		element = element || this.element;
		return element.insertAfter(newElement, referenceElement);
	},
	
    insertBefore: function(newNode, existingNode, element){
		element = element || this.element;
		return element.insertBefore(newNode, existingNode);
    },
    
    replaceChild : function(newChild, oldChild){
		if(newChild && oldChild) {
			var parentNode = oldChild.parentNode;
			do { 
				var el = parentNode.replaceChild(newChild, oldChild);
				return el;
			} while (parentNode = oldChild.parentNode);
		}
	},
    
    removeChild : function(element){
		element = element||this.element;
		var parentNode = element.parentNode;
		do {
			var el = parentNode.removeChild(element);
			return el;
		} while (parentNode = element.parentNode);
	},
    
    appendChild : function(child, slot, element){
		element = element||this.element;
		slot = (typeof slot === "string") ? this.querySelector(slot) : slot;
		slot = (slot)? slot:element;
		slot.appendChild((child instanceof w3c.Node || child.element) ? child.element:child);
		return child;
	},
    
    hasChildNodes: function(){
		return (this.childNodes().length > 0);
    },
    
    cloneNode : function(deep){
		deep = (typeof deep !== "undefined")? deep:true;
		return new this.constructor({}, this.element.cloneNode(deep));
	},
    
    normalize: function(){
		throw new Error("w3c.Node#normalize() not yet implemented");
	},
    
    isSupported: function(){
		throw new Error("w3c.Node#isSupported() not yet implemented");
    },
    
    namespaceURI: function(){
		throw new Error("w3c.Node#namespaceURI() not yet implemented");
    },
    
    isSameNode: function(){
		throw new Error("w3c.Node#isSameNode() not yet implemented");
    },
    
    isEqualNode: function(){
		throw new Error("w3c.Node#isEqualNode() not yet implemented");
    }
});
